#include "TransformWrap.h"
#include "../render_v1.h"
#include "GameObjectWrap.h"

namespace hxe {
    static int setPosition(lua_State *L)
    {
        Transform* t = (Transform*)(HLuaInst->fastGetCObj(1));
        float x = (float)lua_tonumber(L, 2);
        float y = (float)lua_tonumber(L, 3);
        float z = (float)lua_tonumber(L, 4);
        t->position = Vector3(x, y, z);
        return 0;
    }

    static int setScale(lua_State *L)
    {
        Transform* t = (Transform*)(HLuaInst->fastGetCObj(1));
        float x = (float)lua_tonumber(L, 2);
        float y = (float)lua_tonumber(L, 3);
        float z = (float)lua_tonumber(L, 4);
        t->scale = Vector3(x, y, z);
        return 0;
    }

    static int setEulerAngles(lua_State *L)
    {
        Transform* t = (Transform*)(HLuaInst->fastGetCObj(1));
        float x = (float)lua_tonumber(L, 2);
        float y = (float)lua_tonumber(L, 3);
        float z = (float)lua_tonumber(L, 4);
        t->setEulerAngles(Vector3(x, y, z));
        return 0;
    }

    static int getPosition(lua_State *L)
    {
        Transform* t = (Transform*)(HLuaInst->fastGetCObj(1));
        float x = t->position.x;
        float y = t->position.y;
        float z = t->position.z;

        lua_pushnumber(L, t->position.x);
        lua_pushnumber(L, t->position.y);
        lua_pushnumber(L, t->position.z);

        return 3;
    }

    static int getGameObject(lua_State *L)
    {
        Transform* t = (Transform*)(HLuaInst->fastGetCObj(1));
        GameObject* g = t->gameObject;
        if (g == nullptr)
        {
            return 0;
        }
        else
        {
            HLuaInst->push(g, GameObjectWrap::metaRef);
            return 1;
        }
    }

    static int getParent(lua_State *L)
    {
        Transform* t = (Transform*)(HLuaInst->fastGetCObj(1));
        Transform* parent = t->getParent();
        if (parent == nullptr)
        {
            return 0;
        }
        else
        {
            HLuaInst->push(parent, TransformWrap::metaRef);

            return 1;
        }
    }

    static int setParent(lua_State *L)
    {
        Transform* t = (Transform*)(HLuaInst->fastGetCObj(1));
        Transform* p = (Transform*)(HLuaInst->fastGetCObj(2));
        t->setParent(p);
        return 0;
    }

    static int find(lua_State *L)
    {
        Transform* t = (Transform*)(HLuaInst->fastGetCObj(1));
        const char* name = lua_tostring(L, 2);
        Transform* c = t->find(name);
        if (c == nullptr)
        {
            return 0;
        }
        HLuaInst->push(c, TransformWrap::metaRef);
        return 1;
    }

    static int newObject(lua_State *L)
    {
        GameObject* g = (GameObject*)(HLuaInst->fastGetCObj(1));
        Transform* t = new Transform(g);
        HLuaInst->push(t, TransformWrap::metaRef);
        t->drop();
        return 1;
    }

}

int hxe::TransformWrap::metaRef = 0;

int hxe::TransformWrap::loadWrap(lua_State *L)
{
    lua_newtable(L);

    // gc
    lua_pushstring(L, "__gc");
    lua_pushcclosure(L, HLuaInst->gcObject, 0);
    lua_rawset(L, -3);

    // call
    lua_pushstring(L, "new");
    lua_pushcclosure(L, newObject, 0);
    lua_rawset(L, -3);

    // set
    lua_pushstring(L, "__newindex");
    lua_newtable(L);
    lua_pushcclosure(L, HLuaInst->objNewIndexer, 1);
    lua_rawset(L, -3);

    // get
    lua_pushstring(L, "__index");
    lua_newtable(L);

    lua_pushstring(L, "SetPosition");
    lua_pushcclosure(L, setPosition, 0);
    lua_rawset(L, -3);

    lua_pushstring(L, "SetScale");
    lua_pushcclosure(L, setScale, 0);
    lua_rawset(L, -3);

    lua_pushstring(L, "SetEulerAngles");
    lua_pushcclosure(L, setEulerAngles, 0);
    lua_rawset(L, -3);

    lua_pushstring(L, "GetPosition");
    lua_pushcclosure(L, getPosition, 0);
    lua_rawset(L, -3);

    lua_pushstring(L, "GetParent");
    lua_pushcclosure(L, getParent, 0);
    lua_rawset(L, -3);

    lua_pushstring(L, "SetParent");
    lua_pushcclosure(L, setParent, 0);
    lua_rawset(L, -3);

    lua_pushstring(L, "GetGameObject");
    lua_pushcclosure(L, getGameObject, 0);
    lua_rawset(L, -3);

    lua_pushstring(L, "Find");
    lua_pushcclosure(L, find, 0);
    lua_rawset(L, -3);

    lua_pushcclosure(L, HLuaInst->objIndexer, 1);
    lua_rawset(L, -3);

    lua_pushvalue(L, -1);
    lua_setglobal(L, "Transform");
    metaRef = luaL_ref(L, LUA_REGISTRYINDEX);

    return 0;
}
